#include "cf_common.h"
#include "cf_std.h"
#include "cf_queue.h"
#include "cf_errno.h"
#include "lcf_log.h"

int CFQueueDataInit(CFQueueData* this, void* data)
{
    this->data = data;
    CFListInit(&this->list);
    return 0;
}

int CFQueueDataExit(CFQueueData* this)
{
    this->data = NULL;
    CFListInit(&this->list);
    return 0;
}

CFQueueData* CFQueueDataNew(void* data)
{
    CFQueueData* ret;
    if(!(ret = (CFQueueData*)CFMalloc(sizeof(CFQueueData)))){
        LCF_ERR_OUT(ERR_OUT, "\n");
    }
    if(CFQueueDataInit(ret, data)){
        LCF_ERR_OUT(ERR_FREE_RET, "\n");
    }
    return ret;
ERR_FREE_RET:
    CFFree(ret);
ERR_OUT:
    return NULL;
}

void CFQueueDataFree(CFQueueData* this)
{
    CFQueueDataExit(this);
    CFFree(this);
}

int CFQueueInit(CFQueue* this, int size)
{
    this->size = size;
    this->currSize = 0;
    CFListInit(&this->list);
    return 0;
}

int CFQueuePush(CFQueue* this, void* data)
{
    CFQueueData* newD;
    if(this->currSize+1 > this->size){
        CFErrno = CF_ERR_OVER_MAX_SIZE;
        LCF_ERR_OUT(ERR_OUT, "\n");
    }
    if(!(newD=CFQueueDataNew(data))){
        CFErrno = CF_ERR_ALLOC_MEM;
        LCF_ERR_OUT(ERR_OUT, "\n");
    }
    CFListAppend(&this->list, &newD->list);
    this->currSize++;
    return 0;
ERR_FREE_NEW_DATA:
    CFFree(newD);
ERR_OUT:
    return -1;
}

int CFQueuePop(CFQueue* this, void** data)
{
    CFQueueData* pd;
    if(this->currSize ==0 || CFListGetPrev(&this->list) == &this->list){
        LCF_ERR_OUT(ERR_OUT, "\n");
    }
    pd = CFListGetPrevContainer(&this->list, CFQueueData, list);
    *data = pd->data;
    CFListDel(CFListGetPrev(&this->list));
    CFQueueDataFree(pd);
    this->currSize--;
ERR_OUT:
    return -1;
}

int CFQueueExit(CFQueue* this)
{
    CFListForeachContainerSafe(&this->list, qData, CFQueueData, list){
        CFQueueDataFree(qData);
    }
    return CFQueueInit(this, this->size);
}

